// Copyright DustedPixels.com 2008. All rights reserved.

package com.dustedpixels.asm.analysis;

import org.objectweb.asm.Opcodes;
import org.objectweb.asm.tree.AbstractInsnNode;
import org.objectweb.asm.tree.FieldInsnNode;
import org.objectweb.asm.tree.analysis.AnalyzerException;
import org.objectweb.asm.tree.analysis.BasicValue;
import org.objectweb.asm.tree.analysis.Value;

import com.dustedpixels.asm.Types;


/**
 * @author micapolos@gmail.com (Michal Pociecha-Los)
 */
public final class FieldInterpreter extends InterpreterAdapter {
  public static final class Values {
    public static final Value FIELD = new BasicValue(Types.ofObject());
    public static final Value MAYBE_FIELD = new BasicValue(Types.ofObject());
  }
  
  private final String fieldName;

  public FieldInterpreter(String fieldName) {
    super(new ThisInterpreter());
    this.fieldName = fieldName;
  }
  
  @Override
  public Value merge(Value v, Value w) {
    if (v == Values.FIELD && w != Values.FIELD) {
      return Values.MAYBE_FIELD; 
    } else if (v != Values.FIELD && w == Values.FIELD) {
      return Values.MAYBE_FIELD;
    } else {
      return super.merge(v, w);
    }
  }
  
  @Override
  public Value unaryOperation(AbstractInsnNode insn, Value value) throws AnalyzerException {
    if (value == ThisInterpreter.Values.THIS && insn.getOpcode() == Opcodes.GETFIELD) {
      FieldInsnNode fieldInsn = (FieldInsnNode) insn;
      if (fieldInsn.name.equals(fieldName)) return Values.FIELD;
    }
    return super.unaryOperation(insn, value);
  }
}
